package ru.spb.osll.myfit.client.widget;

import com.google.gwt.cell.client.*;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.view.client.ListDataProvider;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.ProgressCounts;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public class ResultTableWidget extends CellTable<PageExecutingResult> {

    private ListDataProvider<PageExecutingResult> dataProvider;
    private List<PageExecutingResult> results;
    private List<ResultTableEventListener> m_listeners;

    public ResultTableWidget() {
        m_listeners = new LinkedList<ResultTableEventListener>();
        initializeTable();
    }

    private void initializeTable() {
        setWidth("100%", true);
        initTableColumns();

        dataProvider = new ListDataProvider<PageExecutingResult>();
        dataProvider.addDataDisplay(this);
        results = dataProvider.getList();
    }


    private void initTableColumns() {


        Column<PageExecutingResult, PageExecutingResult> pageNameColumn = new Column<PageExecutingResult, PageExecutingResult>(new PageNameCell()) {

            @Override
            public PageExecutingResult getValue(PageExecutingResult object) {
                return object;
            }

        };
        addColumn(pageNameColumn, "Page");

        Column<PageExecutingResult, Date> timeColumn = new Column<PageExecutingResult, Date>(new DateCell(DateTimeFormat.getFormat("dd.MM.yy h:mm a"))) {

            @Override
            public Date getValue(PageExecutingResult object) {
                return object.getStartTime();
            }

        };
        addColumn(timeColumn, "Start Time");

        Column<PageExecutingResult, String> progressColumn = new Column<PageExecutingResult, String>(new TextCell()) {

            @Override
            public String getValue(PageExecutingResult object) {
                return object.getState().toString();
            }

        };
        addColumn(progressColumn, "Progress");

        Column<PageExecutingResult, String> summaryColumn = new Column<PageExecutingResult, String>(new TextCell()) {

            @Override
            public String getValue(PageExecutingResult object) {

                ProgressCounts pCount = object.getCounts();
                int progress = pCount.getProgressSegments();
                int right = pCount.getRight();
                int wrong = pCount.getWrong();
                int ignored = pCount.getIgnores();
                int exceptions = pCount.getExceptions();

                return new String("processed: " + progress + ", right: " + right +
                        ", wrong: " + wrong + ", ignored: " + ignored +
                        ", exceptions: " + exceptions);
            }

        };
        addColumn(summaryColumn, "Summary");

        ActionCell<PageExecutingResult> stopCell = new ActionCell<PageExecutingResult>("Stop", new ActionCell.Delegate<PageExecutingResult>() {

            @Override
            public void execute(PageExecutingResult object) {
                notifyListeners(new ResultTableEvent(ResultTableEvent.ResultTableEventType.STOP_EXECUTION, object));
            }
        });

        Column<PageExecutingResult, PageExecutingResult> stopColumn = new Column<PageExecutingResult, PageExecutingResult>(new StopButtonCell("Stop", "")) {

            @Override
            public PageExecutingResult getValue(PageExecutingResult object) {
                return object;
            }

        };
        addColumn(stopColumn, "Stop");
        setColumnWidth(stopColumn, 100, com.google.gwt.dom.client.Style.Unit.PX);

    }

    public void addResult(final PageExecutingResult result) {
        if (findListElementByID(results, result.getID()) != -1)
            return;
        results.add(result);
    }

    public void removeResult(String id) {
        int index = findListElementByID(results, id);
        if (index != -1)
            results.remove(index);
        dataProvider.flush();
    }

    public void updateResult(final PageExecutingResult result) {
        int index = findListElementByID(results, result.getID());
        if (index == -1)
            return;
        results.set(index, result);
        dataProvider.flush();
    }


    public void addResultTableEventListener(ResultTableEventListener listener) {
        m_listeners.add(listener);
    }

    public void removeResultTableEventListener(ResultTableEventListener listener) {
        m_listeners.remove(listener);
    }

    private void notifyListeners(ResultTableEvent event) {
        for (ResultTableEventListener l : m_listeners)
            l.actionPerformed(event);
    }

    private class PageNameCell extends AbstractCell<PageExecutingResult> {

        public PageNameCell() {
            super("click");
        }

        @Override
        public void render(com.google.gwt.cell.client.Cell.Context context,
                           PageExecutingResult value, SafeHtmlBuilder sb) {
            sb.appendHtmlConstant("<div class='testResultTablePageName'>" + value.getName() + "</div>");
        }

        public void onBrowserEvent(Context context, Element parent, PageExecutingResult value,
                                   NativeEvent event, ValueUpdater<PageExecutingResult> valueUpdater) {
            if (value == null) {
                return;
            }

            super.onBrowserEvent(context, parent, value, event, valueUpdater);

            if ("click".equals(event.getType())) {
                notifyListeners(new ResultTableEvent(ResultTableEvent.ResultTableEventType.OPEN_PAGE_RESULT, value));
            }
        }

    }

    private class StopButtonCell extends AbstractCell<PageExecutingResult> {

        private final String style;
        private final String text;

        public StopButtonCell(String text, String style) {
            super("click");
            this.style = style;
            this.text = text;
        }

        @Override
        public void render(com.google.gwt.cell.client.Cell.Context context,
                           PageExecutingResult value, SafeHtmlBuilder sb) {
            StringBuilder html = new StringBuilder();
            html.append("<button class='").append(style).append('\'');
            if (value.getState().equals(PageExecutingResult.PageExecutingState.FINISH)
                    || value.getState().equals(PageExecutingResult.PageExecutingState.FAIL))
                html.append("disabled='disabled'");
            html.append('>').append(text).append("</button>");
            sb.appendHtmlConstant(html.toString());
        }

        public void onBrowserEvent(Context context, Element parent, PageExecutingResult value,
                                   NativeEvent event, ValueUpdater<PageExecutingResult> valueUpdater) {
            if (value == null) {
                return;
            }

            super.onBrowserEvent(context, parent, value, event, valueUpdater);

            if ("click".equals(event.getType())) {
                notifyListeners(new ResultTableEvent(ResultTableEvent.ResultTableEventType.STOP_EXECUTION, value));
            }
        }

    }

    private int findListElementByID(List<PageExecutingResult> l, String id) {
        PageExecutingResult r;
        for (int i = 0; i < l.size(); i++) {
            r = l.get(i);
            if (r.getID().equals(id))
                return i;
        }
        return -1;
    }
}